﻿#include "CameraBase.h"
#include <QTimer>
#include <QDebug>

#pragma execution_character_set("utf-8")
QMap<CameraStatus,QString> CameraBase::mapStatusStr{};
QMap<CameraTriggerType,QString> CameraBase::mapTrigModeStr{};
QMap<CameraErrorCode, QString> CameraBase::mapErrorCodeStr{};
QMap<int, QString> CameraBase::mapWBModeStr{};
QMap<int, QString> CameraBase::mapExpAutoStr{};
QMap<int, QString> CameraBase::mapGainModeStr{};
QMap<int, QString> CameraBase::mapCameraBrand{};
void CameraBase::initStaticValue()
{
    CameraBase::mapStatusStr = {{CS_Unavailable,QObject::tr("<font color=\'red\'>不可用</font>")},
                                {CS_Opened,QObject::tr("<font color=\'yellow\'>相机打开</font>")},
                                {CS_Grabbing,QObject::tr("<font color=\'green\'>相机采集</font>")},
                                {CS_Closing,QObject::tr("<font color=\'red\'>相机关闭中</font>")},
                                {CS_Closed,QObject::tr("<font color=\'red\'>相机关闭</font>")}};

    CameraBase::mapTrigModeStr = {{CTT_Off, "Off"},
                                  {CTT_Line0, "Line0"},
                                  {CTT_Line1, "Line1"},
                                  {CTT_Line2, "Line2"},
                                  {CTT_Line3, "Line3"},
                                  {CTT_Software, "Software"},
                                  {CTT_FrequencyConverter, "Converter"},
                                  };

    CameraBase::mapErrorCodeStr = {{CEC_ImgError, "图像错误"},
                                   {CEC_Remove, "相机连接断开"}};

    CameraBase::mapWBModeStr = {{0, "Off"},
                                {1, "Once"},
                                {2, "Continuous"},
                                };
    CameraBase::mapExpAutoStr = {{0, "Off"},
                                 {1, "Once"},
                                 {2, "Continuous"},
                                 };
    CameraBase::mapGainModeStr = {{0, "Off"},
                                  {1, "Once"},
                                  {2, "Continuous"},
                                  };
    CameraBase::mapCameraBrand = {{CB_HiK, "海康"},
                                  {CB_Basler, "巴斯勒"},
                                  {CB_DaHua, "大华"},
                                  {CB_DaHeng, "大恒"},
                                  {CB_Ik, "埃科"},
                                  };
}

CameraBase::CameraBase(QObject *parent) : QObject(parent)
{
    mReconnectMax = 1000;
    mReconnectCnt = 0;
    qRegisterMetaType<ImageInfo>("ImageInfo");
    qRegisterMetaType<ImageInfo>("ImageInfo&");
    qRegisterMetaType<FloatValue>("FloatValue");
    qRegisterMetaType<FloatValue>("FloatValue&");
    qRegisterMetaType<IntValue>("IntValue");
    qRegisterMetaType<IntValue>("IntValue&");
    qRegisterMetaType<CameraBrightness>("CameraBrightness");
    qRegisterMetaType<CameraBrightness>("CameraBrightness&");
    qRegisterMetaType<CameraROI>("CameraROI");
    qRegisterMetaType<CameraROI>("CameraROI&");
    qRegisterMetaType<CameraTrigger>("CameraTrigger");
    qRegisterMetaType<CameraTrigger>("CameraTrigger&");
    qRegisterMetaType<CameraWhiteBalance>("CameraWhiteBalance");
    qRegisterMetaType<CameraWhiteBalance>("CameraWhiteBalance&");
    qRegisterMetaType<CameraStatus>("CameraStatus");
    qRegisterMetaType<CameraStatus>("CameraStatus&");
    qRegisterMetaType<std::string>("std::string");
    qRegisterMetaType<std::string>("std::string&");
    qRegisterMetaType<CameraFrameRate>("CameraFrameRate");
    qRegisterMetaType<CameraFrameRate>("CameraFrameRate&");
    qRegisterMetaType<CameraTrans>("CameraTrans");
    qRegisterMetaType<CameraTrans>("CameraTrans&");
    qRegisterMetaType<CameraErrorCode>("CameraErrorCode");
    qRegisterMetaType<CameraErrorCode>("CameraErrorCode&");
    qRegisterMetaType<CameraBrand>("CameraBrand");
    qRegisterMetaType<CameraBrand>("CameraBrand&");
    initStaticValue();

}

CameraBase::~CameraBase()
{

}

void CameraBase::setStatus(const CameraStatus &status)
{
    if(status == mStatus )
        return;
    mStatus = status;
    emit sigStatusChanged(mCamConfig.name,mStatus);
}

void CameraBase::onInit()
{
    initialize();
    openCamera();
    startGrabbing();
    if(mStatus != CS_Grabbing){
        reStart();
    } else {
        emit sigStartSucceed(mCamConfig.name);
    }
}

void CameraBase::quit()
{
    mIsQuit = true;
    stopGrabbing();
    closeCamera();
    releaseCamera();
    deleteLater();
}


void CameraBase::reStart()
{
    QTimer::singleShot(1000, [&](){
        if(mIsQuit)
            return;
        if(mReconnectCnt >= mReconnectMax){
            return;
        }
        ++mReconnectCnt;
        releaseCamera();
        initialize();
        openCamera();
        startGrabbing();
        if(mStatus != CS_Grabbing){
            reStart();
        }else{
            mReconnectCnt = 0;
            emit sigStartSucceed(mCamConfig.name);
        }
    });
}

void CameraBase::readConfig(const QString &camName)
{
    if(camName != mCamConfig.name)
        return;
    mCamConfig.isColor = isColor(getPixelFormat());
    mCamConfig.isLine = isLineScan(getScanType());
    readROI(camName);
    readWhiteBalance(camName);
    readBrightness(camName);
    readTrigger(camName);
    readTrans(camName);
    readFrameRate(camName);
    readFrequencyConverter(camName);
    emit sigConfig(mCamConfig);
}

void CameraBase::onConfigChanged(const CameraConfig &config)
{
    if(config.name != mCamConfig.name)
        return;
    mCamConfig = config;
    stopGrabbing();
    setROI(config.name, config.roi);
    setWhiteBalance(config.name, config.wb);
    setBrightness(config.name, config.bright);
    setTrigger(config.name, config.trig);
    setTrans(config.name, config.trans);
    setFrameRate(config.name, config.rate);
    setFrequencyConverter(config.name, config.fc);
    startGrabbing();
}

void CameraBase::setConfig(const CameraConfig &config)
{
    mCamConfig = config;
}

void CameraBase::readROI(const QString& camName)
{
    if(camName != mCamConfig.name)
        return;
    if(!(mStatus >= CS_Opened))
        return;
    mCamConfig.roi.offX = getOffsetX(mCamConfig.name);
    mCamConfig.roi.offY = getOffsetY(mCamConfig.name);
    mCamConfig.roi.width = getWidth(mCamConfig.name);
    mCamConfig.roi.height = getHeight(mCamConfig.name);
    emit sigROI(mCamConfig.name, mCamConfig.roi);
}
void CameraBase::readWhiteBalance(const QString& camName)
{
    if(camName != mCamConfig.name)
        return;
    if(!(mStatus >= CS_Opened))
        return;
    if(isColor(getPixelFormat())){
        mCamConfig.wb.wbMode = getWhiteBalanceMode(mCamConfig.name);
        if(mCamConfig.wb.wbMode == 0){
            mCamConfig.wb.wbR = getWhiteBalanceR(mCamConfig.name);
            mCamConfig.wb.wbG = getWhiteBalanceG(mCamConfig.name);
            mCamConfig.wb.wbB = getWhiteBalanceB(mCamConfig.name);
        }
        emit sigWhiteBalance(mCamConfig.name, mCamConfig.wb);
    }
}
void CameraBase::readBrightness(const QString& camName)
{
    if(camName != mCamConfig.name)
        return;
    if(!(mStatus >= CS_Opened))
        return;
    mCamConfig.bright.expMode = getExposureAutoMode(mCamConfig.name);
    mCamConfig.bright.exp = getExposureTime(mCamConfig.name);
    mCamConfig.bright.gainMode = getGainMode(mCamConfig.name);
    mCamConfig.bright.gain = getGain(mCamConfig.name);
    emit sigBrightness(mCamConfig.name, mCamConfig.bright);
}
void CameraBase::readTrigger(const QString& camName)
{
    if(camName != mCamConfig.name)
        return;
    if(!(mStatus >= CS_Opened))
        return;
    mCamConfig.trig.frameMode = getFrameTriggerMode(mCamConfig.name);
    mCamConfig.trig.frameDelay = getFrameTriggerDelay(mCamConfig.name);
    if(isLineScan(getScanType())){
        mCamConfig.trig.lineMode = getLineTriggerMode(mCamConfig.name);
    }
    emit sigTrigger(mCamConfig.name, mCamConfig.trig);
}

void CameraBase::readTrans(const QString &camName)
{
    if(camName != mCamConfig.name)
        return;
    if(!(mStatus >= CS_Opened))
        return;
    mCamConfig.trans.reverseX = getReverseX(mCamConfig.name);
    mCamConfig.trans.reverseY = getReverseY(mCamConfig.name);
    emit sigTrans(mCamConfig.name, mCamConfig.trans);
}

void CameraBase::readFrameRate(const QString &camName)
{
    if(camName != mCamConfig.name)
        return;
    if(!(mStatus >= CS_Opened))
        return;
    mCamConfig.rate.rateControl = getFrameRateControl(mCamConfig.name);
    mCamConfig.rate.rate = getFrameRate(mCamConfig.name);
    emit sigFrameRate(mCamConfig.name, mCamConfig.rate);
}
void CameraBase::readFrequencyConverter(const QString &camName)
{
    if(camName != mCamConfig.name)
        return;
    if(!(mStatus >= CS_Opened))
        return;
    if(isLineScan(getScanType())){
        mCamConfig.fc.preDiv = getPreDiv(mCamConfig.name);
        mCamConfig.fc.mul = getMul(mCamConfig.name);
        mCamConfig.fc.postDiv = getPostDiv(mCamConfig.name);
    }
    emit sigFrequencyConverter(mCamConfig.name, mCamConfig.fc);
}

void CameraBase::setROI(const QString& camName, const CameraROI &roi)
{
    if(camName != mCamConfig.name)
        return;
    mCamConfig.roi = roi;
    if(!(mStatus == CS_Opened))
        return;
    setWidth(camName,roi.width.val);
    setHeight(camName,roi.height.val);
    setOffsetX(camName,roi.offX.val);
    setOffsetY(camName,roi.offY.val);
}
void CameraBase::setWhiteBalance(const QString& camName, const CameraWhiteBalance &cw)
{
    if(camName != mCamConfig.name)
        return;
    mCamConfig.wb = cw;
    if(!(mStatus >= CS_Opened))
        return;
    if(isColor(getPixelFormat())){
        setWhiteBalanceMode(camName, cw.wbMode);
        if(cw.wbMode == 0){
            setWhiteBalanceR(camName,cw.wbR.val);
            setWhiteBalanceG(camName,cw.wbG.val);
            setWhiteBalanceB(camName,cw.wbB.val);
        }
    }
}
void CameraBase::setBrightness(const QString& camName,  const CameraBrightness &cb)
{
    if(camName != mCamConfig.name)
        return;
    mCamConfig.bright = cb;
    if(!(mStatus >= CS_Opened))
        return;
    setGainMode(camName, cb.gainMode);
    if(cb.gainMode == 0){
        setGain(camName, cb.gain.val);
    }
    setExposureAutoMode(camName, cb.expMode);
    if(cb.expMode == 0){
        setExposureTime(camName, cb.exp.val);
    }
}
void CameraBase::setTrigger(const QString& camName, const CameraTrigger &ct)
{
    if(camName != mCamConfig.name)
        return;
    mCamConfig.trig = ct;
    if(!(mStatus == CS_Opened))
        return;
    setFrameTriggerMode(camName, ct.frameMode);
    if(ct.frameMode != CTT_Off){
        setFrameTriggerDelay(camName, ct.frameDelay.val);
    }
    if(isLineScan(getScanType())){
        setLineTriggerMode(camName, ct.lineMode);
    }
}

void CameraBase::setTrans(const QString &camName, const CameraTrans &cts)
{
    if(camName != mCamConfig.name)
        return;
    mCamConfig.trans = cts;
    if(!(mStatus == CS_Opened))
        return;
    setReverseX(camName,cts.reverseX);
    setReverseY(camName,cts.reverseY);
}

void CameraBase::setFrameRate(const QString &camName, const CameraFrameRate &cts)
{
    if(camName != mCamConfig.name)
        return;
    mCamConfig.rate = cts;
    if(!(mStatus == CS_Opened))
        return;
    setFrameRateControl(camName,cts.rateControl);
    if(cts.rateControl){
        setFrameRate(camName,cts.rate.val);
    }
}

void CameraBase::setFrequencyConverter(const QString &camName, const FrequencyConverter &cfc)
{
    if(camName != mCamConfig.name)
        return;
    mCamConfig.fc = cfc;
    if(!(mStatus == CS_Opened))
        return;
    if(isLineScan(getScanType())){
        setPreDiv(camName, cfc.preDiv.val);
        setMul(camName, cfc.mul.val);
        setPostDiv(camName, cfc.postDiv.val);
    }
}

